import express from 'express';
import fs from 'fs';
const app = express();
// 第一步：电脑端登录，获取Cookie。获取在线设备 -> 如果有设备在线 -> 踢设备下线 -> 如果没有则下一步
// 第二步：创建createSession -> 获取在线设备 -> 获取各种信息
// 第三步：三个线程请求话术文本 ->  切割话术 -> 如果数组长度为30以内，重新请求并添加
// 第四步：循环数组，请求语音地址并下载


let Cookie = ``;
const configPath = './pull_audio.config.json';

const loadConfig = (configPath) => {
  try {
    const rawData = fs.readFileSync(configPath);
    return JSON.parse(Buffer.from(rawData).toString().replace(/\\/g, '\\\\'));
  } catch (err) {
    console.error('配置文件读取失败:', err);
    return null;
  }
};

const configJson = loadConfig(configPath);
Cookie = configJson.Cookie;
let URL = configJson.URL;
let SelfTtsHost = configJson.SelfTtsHost;

const PORT = configJson.PORT;
const TIME = Number(configJson.TIME);



let OpenId = ``;
let SessionToken = ``;
let WebId = ``;



// 获取在线设备
const getSessionList = async (cookie) => {
  return new Promise(async (resolve, reject) => {
    try {
      const response = await fetch("http://douyin.toloho.ltd/index/ailive2/getSessionList", {
        headers: {
          'Cookie': cookie
        },
        credentials: 'include', // 自动携带当前域cookie
        method: "GET",
        mode: "cors",
      });

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        result += decoder.decode(value);
      }
      const parsedResult = JSON.parse(result);
      console.log(parsedResult);

      resolve(parsedResult);
    } catch (error) {
      reject(error);
    }
  });
};

// 结束在线设备
const endSession = async ({ open_id, session_token, web_id, cookie }) => {
  return new Promise(async (resolve, reject) => {
    try {
      const requestBody = {
        session_token: session_token,
        web_id: web_id
      };

      const response = await fetch("http://douyin.toloho.ltd/index/ailive2/endSession", {
        headers: {
          'Cookie': cookie,
          "accept": "application/json, text/plain, */*",
          "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7",
          "content-type": "application/json;charset=UTF-8"
        },
        credentials: "include",
        referrer: `http://douyin.toloho.ltd/index/ailive2?open_id=${open_id}`,
        referrerPolicy: "strict-origin-when-cross-origin",
        body: JSON.stringify(requestBody),
        method: "POST",
        mode: "cors"
      });

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        result += decoder.decode(value);
      }
      const parsedResult = JSON.parse(result);
      console.log(parsedResult);

      resolve(parsedResult);

    } catch (error) {
      reject(error);
    }
  });
};


//  创建在线
const createSession = ({ open_id, self_tts_host, entire_text, extract_info, info_text, web_id, cookie }) => {
  const data = {
    "open_id": open_id,
    "room_id": "",
    "computilityType": 1,
    "self_tts_host": self_tts_host,
    "entire_text": entire_text,
    "extract_info": extract_info,
    "info_text": info_text,
    "selectedRefAudio": "",
    "rewriteMode": 1,
    "welcomeFlag": false,
    "replyFlag": true,
    "speed": "1.0",
    "ignore_users": "品牌厨电源头工厂店",
    "replyTemplate": "{评论内容}，{用户昵称}，呃，{回复}",
    "selectedRefAssiAudio": "",
    "forbiddenWords": "",
    "web_id": web_id,
    "platform": "douyin"
  };

  return new Promise(async (resolve, reject) => {
    try {
      const response = await fetch("http://douyin.toloho.ltd/index/ailive2/createSession", {
        headers: {
          'Cookie': cookie,
          "accept": "application/json, text/plain, */*",
          "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7",
          "content-type": "application/json;charset=UTF-8"
        },
        credentials: "include",
        referrer: `http://douyin.toloho.ltd/index/ailive2?open_id=${open_id}`,
        referrerPolicy: "strict-origin-when-cross-origin",
        body: JSON.stringify(data),
        method: "POST",
        mode: "cors",

      });

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        result += decoder.decode(value);
      }

      const parsedResult = JSON.parse(result);
      console.log(result);

      resolve(parsedResult);
    } catch (error) {
      reject(error);
    }
  });
};


// 获取话术长文本
const sectionRewrite = ({ session_token, open_id, cookie }) => {
  const batchDecode2 = (unicodeStr) => {
    return unicodeStr.replace(/\\u[\dA-F]{4}/gi,
      match => String.fromCharCode(parseInt(match.slice(2), 16)));
  };

  return new Promise((resolve, reject) => {
    const body = {
      text: '--\n',
      info_text: '\n请多主动跟观众互动',
      session_token: session_token
    };

    fetch("http://douyin.toloho.ltd/index/ailive2/sectionRewrite", {
      headers: {
        'Cookie': cookie,
        "accept": "*/*",
        "accept-language": "zh-CN,zh;q=0.9",
        "content-type": "application/json",
        "proxy-connection": "keep-alive"
      },
      credentials: "include",
      referrer: `http://douyin.toloho.ltd/index/ailive2?open_id=${open_id}`,
      referrerPolicy: "strict-origin-when-cross-origin",
      body: JSON.stringify(body),
      method: "POST",
      mode: "cors",
    })
      .then(async response => {
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let result = '';

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          result += decoder.decode(value);
        }

        const parsedResult = JSON.parse(batchDecode2(result)).content;
        console.log(parsedResult);

        resolve(parsedResult);
      })
      .catch(error => {
        reject(error);
      });
  });
};
// sectionRewrite({ session_token: SessionToken, open_id: OpenId, cookie: Cookie });

// 根据自定义文本转语音
const tts = ({ text, open_id, session_token, self_tts_host, web_id, cookie }) => {
  return new Promise(async (resolve, reject) => {
    try {
      const requestBody = {
        user: "",
        rewrite: "0",
        text: text,
        assistText: "",
        assistOverlap: 0,
        voice_md5: "",
        assi_voice_md5: "",
        speed: "1.0",
        open_id: open_id,
        room_id: "",
        info_text: "--",
        self_tts_host: self_tts_host,
        session_token: session_token,
        web_id: web_id
      };

      const response = await fetch("http://douyin.toloho.ltd/index/ailive2/tts", {
        headers: {
          'Cookie': cookie,
          "accept": "*/*",
          "accept-language": "zh-CN,zh;q=0.9",
          "content-type": "application/json"
        },
        credentials: "include",
        referrer: `http://douyin.toloho.ltd/index/ailive2?open_id=${open_id}`,
        referrerPolicy: "strict-origin-when-cross-origin",
        body: JSON.stringify(requestBody),
        method: "POST",
        mode: "cors",
      });

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        result += decoder.decode(value);
      }

      const parsedResult = JSON.parse(result);
      console.log(parsedResult);

      resolve(parsedResult);
    } catch (error) {
      reject(error);
    }
  });
};
// const data = tts({ text: "哥姐们听好了哈，你们就尽管放心大胆地把这洗衣液带回家用，咱这服务那完全是杠杠的。", session_token: SessionToken, open_id: OpenId, cookie: Cookie, self_tts_host: SelfTtsHost, web_id: WebId, });

// 发送请求在后端，保存
const saveAudio = (data) => {
  return new Promise(async (resolve, reject) => {
    try {

      const requestBody = {
        "src_text": "现在咱直播间里这么多人，肯定很多人都在下单，库存也有限的，没下单的家人们速度要快，晚了可能就抢不到这个优惠啦。",
        "text": "现在咱直播间里这么多人，肯定很多人都在下单，库存也有限的，没下单的家人们速度要快，晚了可能就抢不到这个优惠啦。",
        "audio": "http:\/\/00_ff_21_0c_6c_84.frp.toloho.ltd:18080\/audio_tmp\/bc88539ca2b5b2be32cef3c2d8350cd1.mp3",
        "ccp_remain": 111660,
        "dtype": "url",
        "ftype": "audio\/wav",
        "logId": "61337334"
      };

      const response = await fetch(URL, {
        method: "POST",
        body: JSON.stringify(data),
      });

      resolve(response);
    } catch (error) {
      reject(error);
    }
  });
};


// 文本大于10,下一个句号切割

const smartTextSplit = (text) => {
  const result = [];
  let currentSegment = '';
  let charCount = 0;

  for (let i = 0; i < text.length; i++) {
    currentSegment += text[i];
    charCount++;

    // 遇到句号且当前段超过15字时分割
    if (text[i] === '。' && charCount > 15) {
      // 新增：检测{xx}模式
      if (!/{.+?}/.test(currentSegment)) {
        result.push(currentSegment.trim());
      }
      currentSegment = '';
      charCount = 0;
    }
  }

  // 处理剩余内容时也需检测{xx}
  if (charCount > 15 && !/{.+?}/.test(currentSegment)) {
    result.push(currentSegment.trim());
  } else if (currentSegment && !/{.+?}/.test(currentSegment)) {
    if (result.length > 0) {
      result[result.length - 1] += currentSegment;
    } else {
      result.push(currentSegment.trim());
    }
  }

  return result.filter(segment => segment.length > 0);
};
const $loopWithDelay = async (callback, delay, count = -1) => {
  if (count === -1) {
    let i = 0;
    while (true) {
      if (callback) {
        const shouldBreak = await callback(i);
        if (shouldBreak === true) {
          break;
        }
      }

      await new Promise(resolve => setTimeout(resolve, delay));
      i++;
    }
  } else {
    for (let i = 0; i < count; i++) {
      if (callback) {
        const shouldBreak = await callback(i);
        if (shouldBreak === true) {
          break;
        }
      }
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};


const createTts = async (text) => {
  if (!OpenId) return;

  const ttsData = await tts({
    text,
    session_token: SessionToken,
    open_id: OpenId,
    cookie: Cookie,
    self_tts_host: SelfTtsHost,
    web_id: WebId
  });

  return ttsData;
};

function getRandomItem(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}


const commonText = ['有运费险和七天无理由，拍回去看品质，不喜欢不满意，支持退换！！', '主播同款内衣，夏天穿不蒙不热很透气', '有运费险！七天无理由！支持试穿！直播间就是您的试衣间！', '1号链接无痕养护内衣，亲肤性好，透气性好', '一体式固定被不可拆卸，机洗手洗不跑杯！不窜杯！不变形！', '无痕养护内衣，收侧乳防下垂外扩！'];
// ————————————————————————————————————————————
$loopWithDelay(async () => {
  if (!OpenId) {
    const sessionList = await getSessionList(Cookie);

    OpenId = sessionList['sessions'][0].open_id;
    SessionToken = sessionList['sessions'][0].token;
    WebId = sessionList['sessions'][0].web_id;
    console.log({ session_token: SessionToken, open_id: OpenId, cookie: Cookie, self_tts_host: SelfTtsHost, web_id: WebId, });
  }

}, 1000);


$loopWithDelay(async () => {
  if (!OpenId) {

  } else {
    console.log('自动生成');

    const text = getRandomItem(commonText);
    const ttsData = await createTts(text);
    data.push(ttsData.audio);
  }

}, TIME);


const data = [];

// 中间件：解析application/json格式
app.use(express.json());

// 中间件：解析application/x-www-form-urlencoded格式
app.use(express.urlencoded({ extended: true }));




// 处理GET请求（路径/geadd）
app.get('/getAudio', (req, res) => {
  const queryParams = req.query; // 获取URL参数
  const { uid } = queryParams;

  // count0为没有音频，1为有音频
  const returnData = {
    count: 0,
    url: '',
    msg: ''
  };

  if (data.length < 1) {
    returnData.count = 0;
    returnData.url = '';
    returnData.msg = '不存在需要播放的音频';
  } else {
    returnData.count = 1;
    returnData.url = data.splice(0, 1);
    returnData.msg = '需要播放的音频';
  }

  res.json(returnData);
});

// 处理POST请求（路径/asdas）
app.get('/addAudio', async (req, res) => {

  const bodyData = req.query; // 获取URL参数

  console.log(bodyData);

  const { text, uid } = bodyData;
  const returnData = {
    code: 0,
    url: '',
    msg: ''
  };

  const ttsData = await createTts(text);
  returnData.url = ttsData.audio;
  returnData.msg = '生成成功';

  data.push(returnData.url);

  res.json(returnData);
});

app.listen(PORT, () => {
  console.log(`服务运行在 http://localhost:${PORT}`);
});



// ————————————————————————————————————————————